// 使用示例
// const runtime = new WasmRuntime(memory);
// const wasm = await runtime.instantiate("module.wasm");

export default class WasmRuntime {
  constructor(memory) {
    this.memory = memory || new WebAssembly.Memory({ initial: 1 });
    this.table = new WebAssembly.Table({ initial: 0, element: "anyfunc" });
    this.imports = {
      env: this.getEnvImports(),
    };
  }

  getEnvImports() {
    return {
      memory: this.memory,
      table: this.table,
      abort: this.handleAbort.bind(this),
      // 其他运行时函数
      __memory_base: 0,
      __table_base: 0,
    };
  }

  handleAbort(msgPtr, filePtr, line, col) {
    const memoryView = new Uint8Array(this.memory.buffer);
    const getString = (ptr) => {
      let end = ptr;
      while (memoryView[end]) end++;
      return new TextDecoder().decode(memoryView.subarray(ptr, end));
    };

    const error = new Error(
      `WASM abort: ${getString(msgPtr)} at ${getString(filePtr)}:${line}:${col}`
    );
    error.name = "WasmAbortError";
    throw error;
  }

  async instantiate(url) {
    const wasm = await WebAssembly.instantiateStreaming(
      fetch(url),
      this.imports
    );
    return wasm;
  }
}
